/*
 * main.cpp
 *
 *  Created on: 20 juin 2011
 *      Author: Pierrick Caillon <pierrick@megami.fr>
 */

#include <DataFile.h>
#include "SourceBuilder.h"
#include "CommandLine.h"
#include "MapRenderer.h"
#include "ISource.h"
#include <fstream>

namespace po = boost::program_options;
po::options_description genericOptions("Generic options");
po::options_description &initMainParams();
CommandLine::Register regIMP(initMainParams, CommandLine::OPT_CLI_HELP);

struct Result
{
	int result;
	Result(int result = 0) :
		result(result)
	{
	}
};

class Main
{
private:
	ISource *builder;
public:
	Main();
	~Main();
	void Init(int argc, char * *argv);
	void Do();
};

int main(int argc, char * * argv)
{
	Main app;
	try
	{
		app.Init(argc, argv);
		app.Do();
	} catch (Result res)
	{
		return res.result;
	}
	return 0;
}

po::options_description& initMainParams()
{
	genericOptions.add_options()("help,h", "produce help message")(
			"config,c",
			po::value<std::string>(CommandLine::get_ConfigFileRef())->default_value(
					"/etc/maprender.cfg"), "name of a configuration file.");
	return genericOptions;
}

void Main::Do()
{
	this->builder = SourceBuilder::get_FirstSource();
	if (builder == NULL)
	{
		std::cerr << __N("Unable to determine the data source.\n");
		throw Result(-2);
	}
	NamedBinaryTag::DataFile nbtFile = this->builder->GetDataFile();
	if (!nbtFile.get_RootTag()->ContainsKey("data"))
	{
		std::cerr
				<< __N("Unable to read the source or the source is not a map file.\n");
		throw Result(-3);
	}
	MapRenderer renderer;
	std::string outputFileName = CommandLine::get_Item("output-file").as<
			std::string> ();
	std::ostream* output = NULL;
	std::ofstream outputFile;
	if (outputFileName == "-")
	{
		output = &std::cout;
	}
	else
	{
		outputFile.open(outputFileName.c_str(),
				std::ios_base::out | std::ios_base::binary);
		if (!outputFile)
		{
			std::cerr << __N("Unable to open the output file. Existing.")
					<< std::endl;
			throw Result(-4);
		}
		output = &outputFile;
	}
	(*output) << renderer.Render(nbtFile);
}

void Main::Init(int argc, char **argv)
{
	try
	{
		CommandLine::init(argc, argv);
	} catch (po::error &e)
	{
		std::cout << e.what() << std::endl << __N("Use -h for help.\n");
		throw Result(-1);
	}
	if (CommandLine::get_ItemCount("help") > 0)
	{
		std::cout << "maprender [options] [<filename>]\n"
				<< CommandLine::ShowHelp;
		throw Result(0);
	}
}

Main::~Main()
{
	if (this->builder != NULL)
		delete this->builder;
}

Main::Main()
{
	this->builder = NULL;
}
